#!/bin/bash

# uninstall mode: "full" (uninstall app and sandbox containers) or "partial", default "partial" for app pkg
readonly uninstall_mode=${1:-partial}

echo "DisplayLink uninstall script"

are_dl_processes_running()
{
    pgrep DisplayLink &> /dev/null
}

echo -e "\n> DisplayLink uninstaller running in \"${uninstall_mode}\" mode"

get_users()
{
  dscl . list /Users | grep -v -e '^_.*' -e daemon -e nobody
}

transfer_legacy_autostart_settings()
{
  local user=$1
  local dlua_xml
  dlua_xml="/Users/$user/Library/Group Containers/73YQY62QM3.com.displaylink.DisplayLinkShared/Library/Application Support/Logs/.dlua.xml"
  
  local autostart
  autostart=$(grep '<value name="AutoStart">' "$dlua_xml" 2> /dev/null | grep -o 'yes\|no') #read AutoStart value from dlua.xml
  [ -z "$autostart" ] && return
  sed -i '' 's/\<value name="AutoStart"\>[a-z]\{2,3\}\<\/value\>//g' "$dlua_xml" 2> /dev/null #delete AutoStart key from dlua.xml
  
  autostart=$(echo "$autostart" | sed 's/yes/1/g;s/no/0/g') #replace "yes" with 1 and "no" with 0 for coherence in defaults
  su -l "$user" -c "defaults write /Users/$user/Library/Containers/com.displaylink.DisplayLinkUserAgent/Data/Library/Preferences/com.displaylink.DisplayLinkUserAgent.plist AppAutostart $autostart" #transfer legacy value
}

remove_displaylink_useragents_and_daemons_for_all_users()
{
  echo -e "\n> Removing DisplayLink user agents"
  launchctl list | grep DisplayLink &> /dev/null
  local had_deamons_installed=$?

  for user in $(get_users); do
    su -l "$user" -c 'launchctl remove com.displaylink.useragent' # legacy useragent name
    su -l "$user" -c 'launchctl remove com.displaylink.DisplayLink Manager' # legacy useragent name
    su -l "$user" -c 'launchctl remove com.displaylink.DisplayLinkManager' # when running as appstore app this is user daemon
    su -l "$user" -c 'launchctl remove com.displaylink.DisplayLinkLoginHelper' # when running as appstore app this is login helper
    [ "${uninstall_mode}" == "full" ] &&  su -l "$user" -c 'launchctl remove com.displaylink.loginscreen' # pre-login agent for appstore app
    
    [ "${uninstall_mode}" == "partial" ] &&  transfer_legacy_autostart_settings "$user"
    [ "${uninstall_mode}" == "full" ] &&  su -l "$user" -c 'defaults delete com.displaylink.DisplayLinkUserAgent' # delete persistent settings
  done

  echo -e "\n> Removing DisplayLink daemon"
  launchctl remove com.displaylink.displaylinkmanager # legacy daemon name
  launchctl remove com.displaylink.DisplayLinkManager

  if [[ $had_deamons_installed -eq 0 ]]; then
    wait_for_dl_processes_finished 10
  fi
}

remove_sandbox_containers()
{
  echo -e "\n> Remove sandbox containers"
  for i in ~root /Users/*
  do
    echo "$i"
    sudo rm -fr "$i/Library/Containers/com.displaylink.DisplayLink Manager"
    sudo rm -fr "$i/Library/Containers/com.displaylink.DisplayLinkManager"
    sudo rm -fr "$i/Library/Containers/com.displaylink.DisplayLinkLoginHelper"
    sudo rm -fr "$i/Library/Containers/com.displaylink.DisplayLinkUserAgent"

    rm -fr "$i/Library/Group Containers/73YQY62QM3.com.displaylink.DisplayLinkShared"
    rm -fr "$i/Library/Group Containers/com.displaylink.DisplayLinkShared"
  done
}

remove_application_scripts()
{
  echo -e "\n> Remove application scripts"
  for i in ~root /Users/*
  do
    sudo rm -fr "$i/Library/Application Scripts/com.displaylink.DisplayLinkLoginHelper"
    sudo rm -fr "$i/Library/Application Scripts/com.displaylink.DisplayLinkManager"
    sudo rm -fr "$i/Library/Application Scripts/com.displaylink.DisplayLinkUserAgent"
    sudo rm -fr "$i/Library/Application Scripts/com.displaylink.DisplayLink_Manager"
  done
}

terminate_any_remaining_dl_processes()
{
  if are_dl_processes_running; then
    echo "Terminate remaining DisplayLink processes"
    sudo killall -SIGTERM 'DisplayLink Manager'
    sudo killall -SIGTERM DisplayLinkUserAgent
    sudo killall -SIGTERM DisplayLinkManager
  fi

  wait_for_dl_processes_finished 5
  if are_dl_processes_running; then
    echo "Kill remaining DisplayLink processes"
    sudo killall -SIGKILL 'DisplayLink Manager'
    sudo killall -SIGKILL DisplayLinkUserAgent
    sudo killall -SIGKILL DisplayLinkManager
  fi
}

wait_for_dl_processes_finished()
{
  local timeout=$1

  while [[ $(( timeout-- )) -gt 0 ]]
  do
    if ! are_dl_processes_running; then
      echo "All DisplayLink processes are finished"
      break
    fi

    echo "Wait for dl prcesses to finish"
    sleep 1
  done
}

rebuildKextCache()
{
  echo -e "\n> Refresh kext cache"
  touch /System/Library/Extensions
  touch /Library/Extensions
  rm -f /System/Library/Extensions.kextcache
}

removeKEXTs()
{
  local kext_uninstall_flag=/tmp/dl_app_installer_requires_restart

  local kextfiles=(
    "/Library/Extensions/DisplayLinkDriver.kext"
    "/System/Library/Extensions/DisplayLinkDriver.kext"
    "/Library/Extensions/DisplayLinkEthernetDriver.kext"
    "/System/Library/Extensions/DisplayLinkDriver0.9.kext"
    "/System/Library/Extensions/DisplayLinkEthernetDriver.kext"
    "/System/Library/Extensions/DisplayLinkNcmDriver.kext"
    "/System/Library/Extensions/DisplayLinkNullDriver.kext"
  )

  for f in "${kextfiles[@]}"
  do
    if [[ -e $f || -h $f ]]
    then
      echo "Removing $f..."
      if ! rm -R "$f"
      then
        echo "ERROR: Unable to remove $f. Please remove manually."
      fi
      touch "$kext_uninstall_flag"
      echo "$f KEXT successfully removed."
    else
      echo "$f KEXT not found, skipping."
    fi
  done

  if [[ -e $kext_uninstall_flag ]]
  then
    rebuildKextCache
  fi
}

remove_displaylink_useragents_and_daemons_for_all_users
terminate_any_remaining_dl_processes

files=(
    "/Applications/DisplayLink"
    "/Library/Application Support/DisplayLink"
    "/Library/LaunchAgents/73YQY62QM3.com.displaylink.DisplayLinkAPServer.plist"
    "/Library/LaunchAgents/com.displaylink.useragent-prelogin.plist"
    "/Library/LaunchAgents/com.displaylink.useragent.plist"
    "/Library/LaunchDaemons/com.displaylink.displaylinkmanager.plist"
    "/Library/LaunchDaemons/com.displaylink.launchd.plist"
    "/Library/Preferences/com.displaylink.plist"
    "/Library/PrivilegedHelperTools/DisplayLink"
    "/Library/Receipts/DisplayLink Software Installer.pkg"
    "/Library/StartupItems/DisplayLinkAgent"
    "/System/Library/Extensions/DisplayLinkGA.plugin"
    "/System/Library/Extensions/DisplayLinkGA_10.6.plugin"
    "/etc/asl/com.displaylink.windowserver"
    "/var/db/receipts/com.displaylink*"
    "/var/log/displaylink"
)

if [[ ${uninstall_mode} == "full" ]]
then
  files+=("/Applications/DisplayLink Software Uninstaller.app"
        "/Applications/DisplayLink Manager.app"
        "/Library/LaunchAgents/com.displaylink.loginscreen.plist")
fi

for f in "${files[@]}"
do
  if [[ -e $f || -h $f ]]
  then
    echo "Removing $f..."
    if ! rm -R "$f"
    then
      echo "ERROR: Unable to remove $f. Please remove manually."
    fi
    echo "$f successfully removed."
  else
    echo "$f not found, skipping."
  fi
done

removeKEXTs

echo -e "\n> Remove plists from user directories"
for i in ~root /Users/*
do
  rm -vf "$i/Library/Preferences/com.displaylink.displaylinkmanager.plist"
  rm -vf "$i/Library/Preferences/com.displaylink.airdisplaypriority.plist"
done

if [[ ${uninstall_mode} == "full" ]]; then
  remove_sandbox_containers
  remove_application_scripts
fi

echo -e "\n> DisplayLink uninstall script done."



